#include "GfxDriver/WGL/WGLHelper.h"

#include <map>

namespace Orca {

	//--------------------------------------------------------------------------
	GLenum WGLHelper::getGLPrimitiveType(PrimitiveType primType) {

		static std::map<PrimitiveType, GLenum> primTypeMapping;

		if(primTypeMapping.empty()) {

			primTypeMapping[PT_POINT_LIST]		= GL_POINTS;
			primTypeMapping[PT_LINE_LIST]		= GL_LINES;
			primTypeMapping[PT_LINE_STRIP]		= GL_LINE_STRIP;
			primTypeMapping[PT_TRIANGLE_LIST]	= GL_TRIANGLES;
			primTypeMapping[PT_TRIANGLE_STRIP]	= GL_TRIANGLE_STRIP;
			primTypeMapping[PT_TRIANGLE_FAN]	= GL_TRIANGLE_FAN;
		}

		return primTypeMapping[primType];
	}

	//--------------------------------------------------------------------------
	GLsizei WGLHelper::getPrimitiveVertexCnt(PrimitiveType primType, uint32 primCnt) {

		switch(primType) {

			case PT_POINT_LIST:
				return (GLsizei)primCnt;

			case PT_LINE_LIST:
				return (GLsizei)(primCnt << 1); // i.e. primCnt * 2;

			case PT_LINE_STRIP:
				return (GLsizei)primCnt + 1;

			case PT_TRIANGLE_LIST:
				return (GLsizei)( (primCnt << 1) + primCnt ); // primCnt * 3;

			case PT_TRIANGLE_STRIP:
				return (GLsizei)primCnt + 2;

			case PT_TRIANGLE_FAN:
				return (GLsizei)primCnt + 2;
		}

		return 0;
	}

	//--------------------------------------------------------------------------
	uint32 WGLHelper::getBytePerPixel(PixelFormat format) {

		static std::map<PixelFormat, uint32> bytePerPixelMapping;

		if(bytePerPixelMapping.empty()) {

			bytePerPixelMapping[PF_INT8_RGBA] = 4;
			bytePerPixelMapping[PF_INT8_XRGB] = 3;

			bytePerPixelMapping[PF_INT16_ABGR] = 8;
			bytePerPixelMapping[PF_INT16_GR] = 4;

			bytePerPixelMapping[PF_FLOAT16_ABGR] = 8;
			bytePerPixelMapping[PF_FLOAT16_GR] = 4;
			bytePerPixelMapping[PF_FLOAT16_R] = 2;

			bytePerPixelMapping[PF_FLOAT32_ABGR] = 16;
			bytePerPixelMapping[PF_FLOAT32_GR] = 8;
			bytePerPixelMapping[PF_FLOAT32_R] = 4;
		}

		return bytePerPixelMapping[format];
	}

	//--------------------------------------------------------------------------
	void WGLHelper::getGLPixelFormat(
		  PixelFormat format
		, GLint &internalFormat
		, GLenum &srcFormat
		, GLenum &srcDataType) {

		switch(format) {

			case PF_INT8_RGBA:
				internalFormat	= GL_RGBA8;
				srcFormat		= GL_RGBA;
				srcDataType		= GL_UNSIGNED_BYTE;
				break;

			case PF_INT8_XRGB:
				internalFormat	= GL_RGB8;
				srcFormat		= GL_RGB;
				srcDataType		= GL_UNSIGNED_BYTE;
				break;

			case PF_INT16_ABGR:
				internalFormat	= GL_RGBA16;
				srcFormat		= GL_RGBA;
				srcDataType		= GL_UNSIGNED_SHORT;
				break;

			case PF_INT16_GR:
				internalFormat	= GL_LUMINANCE16_ALPHA16;
				srcFormat		= GL_LUMINANCE_ALPHA;
				srcDataType		= GL_UNSIGNED_SHORT;
				break;

			case PF_FLOAT16_ABGR:
				internalFormat	= GL_RGBA16F_ARB;
				srcFormat		= GL_RGBA;
				srcDataType		= GL_FLOAT;
				break;

			case PF_FLOAT16_GR:
				internalFormat	= GL_LUMINANCE_ALPHA16F_ARB;
				srcFormat		= GL_LUMINANCE_ALPHA;
				srcDataType		= GL_FLOAT;
				break;

			case PF_FLOAT16_R:
				internalFormat	= GL_LUMINANCE16F_ARB;
				srcFormat		= GL_LUMINANCE;
				srcDataType		= GL_FLOAT;
				break;

			case PF_FLOAT32_ABGR:
				internalFormat	= GL_RGBA32F_ARB;
				srcFormat		= GL_RGBA;
				srcDataType		= GL_FLOAT;
				break;

			case PF_FLOAT32_GR:
				internalFormat	= GL_LUMINANCE_ALPHA32F_ARB;
				srcFormat		= GL_LUMINANCE_ALPHA;
				srcDataType		= GL_FLOAT;
				break;

			case PF_FLOAT32_R:
				internalFormat	= GL_LUMINANCE32F_ARB;
				srcFormat		= GL_LUMINANCE;
				srcDataType		= GL_FLOAT;
				break;

			default:
				break;

		};
	}

	//--------------------------------------------------------------------------
	GLenum WGLHelper::getGLCmpFunc(CmpFunc cmp) {

		static std::map<CmpFunc, GLenum> cmpFuncMapping;

		if( cmpFuncMapping.empty() ) {

			cmpFuncMapping[CMP_NEVER]			= GL_NEVER;
			cmpFuncMapping[CMP_ALWAYS]			= GL_ALWAYS;
			cmpFuncMapping[CMP_EQUAL]			= GL_EQUAL;
			cmpFuncMapping[CMP_NOT_EQUAL]		= GL_NOTEQUAL;
			cmpFuncMapping[CMP_LESS]			= GL_LESS;
			cmpFuncMapping[CMP_LESS_EQUAL]		= GL_LEQUAL;
			cmpFuncMapping[CMP_GREATER]			= GL_GREATER;
			cmpFuncMapping[CMP_GREATER_EQUAL]	= GL_GEQUAL;
		}

		return cmpFuncMapping[cmp];
	}

	//--------------------------------------------------------------------------
	GLenum WGLHelper::getGLBlendFactor(BlendFactor factor) {

		static std::map<BlendFactor, GLenum> blendFactorMapping;

		if( blendFactorMapping.empty() ) {

			blendFactorMapping[BLEND_ONE]					= GL_ONE;
			blendFactorMapping[BLEND_ZERO]					= GL_ZERO;
			blendFactorMapping[BLEND_SRC_COLOR]				= GL_SRC_COLOR;
			blendFactorMapping[BLEND_SRC_ALPHA]				= GL_SRC_ALPHA;
			blendFactorMapping[BLEND_ONE_MINUS_SRC_COLOR]	= GL_ONE_MINUS_SRC_COLOR;
			blendFactorMapping[BLEND_ONE_MINUS_SRC_ALPHA]	= GL_ONE_MINUS_SRC_ALPHA;
			blendFactorMapping[BLEND_DEST_COLOR]			= GL_DST_COLOR;
			blendFactorMapping[BLEND_DEST_ALPHA]			= GL_DST_ALPHA;
			blendFactorMapping[BLEND_ONE_MINUS_DEST_COLOR]	= GL_ONE_MINUS_DST_COLOR;
			blendFactorMapping[BLEND_ONE_MINUS_DEST_ALPHA]	= GL_ONE_MINUS_DST_ALPHA;
		}

		return blendFactorMapping[factor];
	}

	//--------------------------------------------------------------------------

}